package com.yizisu.basemvvm.mvvm.mvvm_helper

import android.os.Looper
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer

/**
 * 若红楼梦空，亦初心不变
 * 作者：thinker
 * 包名：com.yizisu.basemvvm.mvvm.mvvm_helper
 * 时间：2019/5/15 19:22
 * 描述：封装带有状态的liveBean
 */
class LiveBean<T> : MutableLiveData<LiveBeanValue<T>>() {
    var tag: Any? = null
    var valueCall: Function1<T, Unit>? = null
    val status: LiveBeanStatus
        get() = value?.status ?: LiveBeanStatus.START
    val data: T?
        get() = value?.value
    val errorMsg: String?
        get() = value?.errorMsg
    val errorCode: Int?
        get() = value?.errorCode
}

/**
 * 可以添加监听liveBean的中间者
 */
class MediatorLiveBean<T> : MediatorLiveData<LiveBeanValue<T>>() {
    var tag: Any? = null
    var valueCall: Function1<T, Unit>? = null
    val status: LiveBeanStatus
        get() = value?.status ?: LiveBeanStatus.START
    val data: T?
        get() = value?.value
    val errorMsg: String?
        get() = value?.errorMsg
    val errorCode: Int?
        get() = value?.errorCode

    /**
     * 将监听的liveData的值赋给自己
     */
    fun <M> setLiveBean(sourceLiveData: LiveBean<M>, value: T) {
        setLiveDateValue(
            sourceLiveData.status,
            value,
            sourceLiveData.errorMsg,
            sourceLiveData.errorCode
        )
    }

    fun <M> addLiveBeanListener(liveBean: LiveBean<M>, onChanged: Observer<LiveBeanValue<M>>) {
        addSource(liveBean, onChanged)
    }
}


data class LiveBeanValue<T>(
    var status: LiveBeanStatus,
    var value: T?,
    var errorMsg: String? = null,
    var errorCode: Int? = null
)

enum class LiveBeanStatus {
    START,
    SUCCESS,
    FAIL
}

/**
 * 创建一个对象
 */
fun <T> createLiveBean(): LiveBean<T> {
    return LiveBean()
}

/**
 * liveData 状态开始
 */
fun <T> LiveBean<T>.start(clearOldValue: Boolean = false) {
    setLiveDateValue(LiveBeanStatus.START, if (clearOldValue) null else data, errorMsg, errorCode)
}

/**
 * liveData 状态成功
 */
fun <T> LiveBean<T>.success(valueT: T) {
    setLiveDateValue(LiveBeanStatus.SUCCESS, valueT, errorMsg, errorCode)
}

/**
 * liveData 状态错误
 */
fun <T> LiveBean<T>.fail(errorMsg: String, errorCode: Int? = null, clearOldValue: Boolean = false) {
    setLiveDateValue(LiveBeanStatus.FAIL, if (clearOldValue) null else data, errorMsg, errorCode)
}

/**
 * 设置liveDate的值
 */
fun <T> LiveBean<T>.setLiveDateValue(
    status: LiveBeanStatus,
    valueT: T?,
    errorMsg: String?,
    errorCode: Int?
) {
    var liveData = this.value
    if (liveData == null) {
        liveData = LiveBeanValue(LiveBeanStatus.START, null, null)
    }
    liveData.status = status
    liveData.value = valueT
    liveData.errorMsg = errorMsg
    liveData.errorCode = errorCode
    if (Thread.currentThread() == Looper.getMainLooper().thread) {
        value = liveData
    } else {
        postValue(liveData)
    }
}

fun <T> createMediatorLiveBean(): MediatorLiveBean<T> {
    return MediatorLiveBean()
}

/**
 * liveData 状态开始
 */
fun <T> MediatorLiveBean<T>.start(clearOldValue: Boolean = false) {
    setLiveDateValue(LiveBeanStatus.START, if (clearOldValue) null else data, errorMsg, errorCode)
}

/**
 * liveData 状态成功
 */
fun <T> MediatorLiveBean<T>.success(valueT: T) {
    setLiveDateValue(LiveBeanStatus.SUCCESS, valueT, errorMsg, errorCode)
}

/**
 * liveData 状态错误
 */
fun <T> MediatorLiveBean<T>.fail(
    errorMsg: String,
    errorCode: Int? = null,
    clearOldValue: Boolean = false
) {
    setLiveDateValue(LiveBeanStatus.FAIL, if (clearOldValue) null else data, errorMsg, errorCode)
}

/**
 * 设置liveDate的值
 */
fun <T> MediatorLiveBean<T>.setLiveDateValue(
    status: LiveBeanStatus,
    valueT: T?,
    errorMsg: String?,
    errorCode: Int?
) {
    var liveData = this.value
    if (liveData == null) {
        liveData = LiveBeanValue(LiveBeanStatus.START, null, null)
    }
    liveData.status = status
    liveData.value = valueT
    liveData.errorMsg = errorMsg
    liveData.errorCode = errorCode
    if (Thread.currentThread() == Looper.getMainLooper().thread) {
        value = liveData
    } else {
        postValue(liveData)
    }
}